/* command.c */

/********************/
/* SPCORE-COMMAND   */
/* for User-Process */
/* (C) 2003 by NAH6 */
/********************/

/*------------*/
/*  INCLUDES  */
/*------------*/

#include <memory.h>
#include <windows.h>

#include "spipc.h"
#include "winaudio.h"
#include "phone.h"
#include "command.h"
#include "wintop.h"

/*-----------*/
/*  DEFINES  */
/*-----------*/

// changing this to a constant breaks spipc debugging!
#define K_CMD_MSGHDRLEN           sizeof(SPIPC_HEADER)

#define K_CMD_MINQUEUELEN         (1024)
#define K_CMD_EVTQUEUELEN         (2064)
#define K_CMD_EVTWRTIME            (500)

#define K_CMD_ERRMAP11LEN           (15)
#define K_CMD_ERRMAP51LEN           (26)
#define K_CMD_ERRMAP52LEN           (51)
#define K_CMD_ERRMAP61LEN           (65)

/*--------------*/
/*  PROTOTYPES  */
/*--------------*/

static unsigned char cmd__errorconv_disc (signed short err);

/*-------------*/
/*  VARIABLEN  */
/*-------------*/

static void            *cmd_evtbuf;
static void            *cmd_msgbuf;
static unsigned short   cmd_buflen;
static CRITICAL_SECTION cmd_evtlck;

static unsigned char cmd_flgclip;
static unsigned char cmd_flgdisc;

/*====*/

static const unsigned char cmd__errormap11disc[K_CMD_ERRMAP11LEN] =
{
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x1101 E_PHONE_NULLPTR          */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x1102 E_PHONE_NOMEM            */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x1103 E_PHONE_BADPHONE         */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x1104 E_PHONE_ISOFF            */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x1105 E_PHONE_NOCALL           */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x1106 E_PHONE_INUSE            */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x1107 E_PHONE_MODE             */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x1108 E_PHONE_INDEX            */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x1109 E_PHONE_CODEC            */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x110A E_PHONE_SIZE             */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x110B E_PHONE_FULL             */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x110C E_PHONE_TELTHREAD        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x110D E_PHONE_TXEVENT          */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x110E E_PHONE_RXTHREAD         */
  SPIPC_DISCONNECT_LOC_SOFTWARE      /* 0x110F E_PHONE_TXTHREAD         */
};

static const unsigned char cmd__errormap51disc[K_CMD_ERRMAP51LEN] =
{
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x5101 E_HAYES_NULLPTR          */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x5102 E_HAYES_CFG_MDMTYPE      */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x5103 E_HAYES_PAR_LINKSERV     */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x5104 E_HAYES_PAR_LINKCARR     */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x5105 E_HAYES_PAR_LINKPROT     */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x5106 E_HAYES_PUT_NOECHO       */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x5107 E_HAYES_PUT_ERRECHO      */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x5108 E_HAYES_PUT_BADECHO      */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x5109 E_HAYES_GET_NOREPLY      */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x510A E_HAYES_GET_NOCHAR       */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x510B E_HAYES_GET_ERRDATA      */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x510C E_HAYES_EVT_RINGING      */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x510D E_HAYES_MDM_OK           */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x510E E_HAYES_MDM_RESPONSE     */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x510F E_HAYES_MDM_ERROR        */
  SPIPC_DISCONNECT_MDM_UNSPECIFIED,  /* 0x5110 E_HAYES_MDM_CMEERR       */
  SPIPC_DISCONNECT_MDM_UNSPECIFIED,  /* 0x5111 E_HAYES_MDM_CMSERR       */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x5112 E_HAYES_MDM_CONNECT      */
  SPIPC_DISCONNECT_USR_HANGUP_REM,   /* 0x5113 E_HAYES_MDM_CARRIER      */
  SPIPC_DISCONNECT_NET_NODIALTONE,   /* 0x5114 E_HAYES_MDM_DIALTONE     */
  SPIPC_DISCONNECT_MDM_LINECURRENT,  /* 0x5115 E_HAYES_MDM_LINEERR      */
  SPIPC_DISCONNECT_USR_BUSY,         /* 0x5116 E_HAYES_MDM_BUSY         */
  SPIPC_DISCONNECT_USR_NOANSWER,     /* 0x5117 E_HAYES_MDM_ANSWER       */
  SPIPC_DISCONNECT_USR_VOICE,        /* 0x5118 E_HAYES_MDM_VOICE        */
  SPIPC_DISCONNECT_NET_DIALDELAY,    /* 0x5119 E_HAYES_MDM_DELAYED      */
  SPIPC_DISCONNECT_NET_BLACKLISTED   /* 0x511A E_HAYES_MDM_BLACKLIST    */
};

static const unsigned char cmd__errormap52disc[K_CMD_ERRMAP52LEN] =
{
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x5201 E_TAPI_NULLPTR           */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5202 E_TAPI_NOMEM             */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5203 E_TAPI_DLLINIT           */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5204 E_TAPI_DLLVER            */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5205 E_TAPI_TSPINIT           */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5206 E_TAPI_TSPVER            */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x5207 E_TAPI_LINENUM           */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5208 E_TAPI_LINECAPS          */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5209 E_TAPI_LINESTAT          */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x520A E_TAPI_ADRNUM            */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x520B E_TAPI_ADRCAPS           */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x520C E_TAPI_ADRSTAT           */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x520D E_TAPI_LINEOPEN          */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x520E E_TAPI_MSGMASK           */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x520F E_TAPI_LINECLOSE         */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5210 E_TAPI_LINESHUTDOWN      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5211 E_TAPI_GETMSG            */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5212 E_TAPI_CALLINFO          */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5213 E_TAPI_CALLSTAT          */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x5214 E_TAPI_ACCEPT1           */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x5215 E_TAPI_ACCEPT2           */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x5216 E_TAPI_NORING            */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x5217 E_TAPI_ANSWER1           */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x5218 E_TAPI_ANSWER2           */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x5219 E_TAPI_LINKSERV          */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x521A E_TAPI_LINKCARR          */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x521B E_TAPI_MAKECALL1         */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x521C E_TAPI_MAKECALL2         */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x521D E_TAPI_GETPORT           */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x521E E_TAPI_CALLCLOSE         */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x521F E_TAPI_CALLDROP          */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x5220 E_TAPI_CALLDEALLOC       */
  SPIPC_DISCONNECT_USR_HANGUP_LOC,   /* 0x5221 E_TAPI_BREAK             */
  SPIPC_DISCONNECT_USR_NOANSWER,     /* 0x5222 E_TAPI_CALL_TIMEOUT      */
  SPIPC_DISCONNECT_USR_UNSPECIFIED,  /* 0x5223 E_TAPI_CALL_UNKNOWN      */
  SPIPC_DISCONNECT_USR_HANGUP_REM,   /* 0x5224 E_TAPI_CALL_HANGUP       */
  SPIPC_DISCONNECT_USR_PICKUP,       /* 0x5225 E_TAPI_CALL_PICKUP       */
  SPIPC_DISCONNECT_USR_FORWARD,      /* 0x5226 E_TAPI_CALL_FORWARDED    */
  SPIPC_DISCONNECT_NET_NODIALTONE,   /* 0x5227 E_TAPI_CALL_DIALTONE     */
  SPIPC_DISCONNECT_NET_OUTOFORDER,   /* 0x5228 E_TAPI_CALL_OUTOFORDER   */
  SPIPC_DISCONNECT_NET_TEMPFAILURE,  /* 0x5229 E_TAPI_CALL_TEMPFAILURE  */
  SPIPC_DISCONNECT_NET_OVERLOAD,     /* 0x522A E_TAPI_CALL_CONGESTION   */
  SPIPC_DISCONNECT_NET_NUMINVALID,   /* 0x522B E_TAPI_CALL_BADADDRESS   */
  SPIPC_DISCONNECT_NET_NUMCHANGED,   /* 0x522C E_TAPI_CALL_NUMCHANGED   */
  SPIPC_DISCONNECT_USR_UNREACHABLE,  /* 0x522D E_TAPI_CALL_UNREACHABLE  */
  SPIPC_DISCONNECT_NET_INCOMPATIBLE, /* 0x522E E_TAPI_CALL_INCOMPATIBLE */
  SPIPC_DISCONNECT_USR_NOANSWER,     /* 0x522F E_TAPI_CALL_NOANSWER     */
  SPIPC_DISCONNECT_USR_BUSY,         /* 0x5230 E_TAPI_CALL_BUSY         */
  SPIPC_DISCONNECT_NET_BLACKLISTED,  /* 0x5231 E_TAPI_CALL_BLOCKED      */
  SPIPC_DISCONNECT_USR_REJECT,       /* 0x5232 E_TAPI_CALL_REJECT       */
  SPIPC_DISCONNECT_USR_DISTURB       /* 0x5233 E_TAPI_CALL_DISTURB      */
};

static const unsigned char cmd__errormap61disc[K_CMD_ERRMAP61LEN] =
{
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x6101 E_SIO_NULLPTR            */
  SPIPC_DISCONNECT_LOC_PARAMETER,    /* 0x6102 E_SIO_OPEN_PORTNUM       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6103 E_SIO_OPEN_CREATE        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6104 E_SIO_OPEN_GETPROP       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6105 E_SIO_OPEN_DEVTYPE       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6106 E_SIO_OPEN_NO8N1         */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6107 E_SIO_OPEN_BAUDRATE      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6108 E_SIO_OPEN_FLOWCTRL      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6109 E_SIO_OPEN_USEDTR        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x610A E_SIO_OPEN_USEDSR        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x610B E_SIO_OPEN_USEDCD        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x610C E_SIO_OPEN_SETBUFFER     */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x610D E_SIO_OPEN_SETMODE       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x610E E_SIO_OPEN_SETTIMER      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x610F E_SIO_OPEN_SETDTR        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6110 E_SIO_OPEN_GETLINE       */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x6111 E_SIO_OPEN_NODSR         */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x6112 E_SIO_OPEN_NOCTS         */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x6113 E_SIO_OPEN_DCDON         */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6114 E_SIO_OPEN_CLRRXERR      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6115 E_SIO_OPEN_CLRRXBUF      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6116 E_SIO_OPEN_OBXNUM        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6117 E_SIO_OPEN_OBXREGOP      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6118 E_SIO_OPEN_OBXREGRD      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6119 E_SIO_OPEN_OBXREGTYP     */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x611A E_SIO_OPEN_OBXREGLEN     */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x611B E_SIO_OPEN_OBXREGWR      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x611C E_SIO_OPEN_OBXDEV        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x611D E_SIO_OPEN_OBXDCTL       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x611E E_SIO_OPEN_RILNUM        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x611F E_SIO_OPEN_RILDLL        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6120 E_SIO_OPEN_RILFKTN       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6121 E_SIO_OPEN_RILEVT        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6122 E_SIO_OPEN_RILINIT       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6123 E_SIO_OPEN_RILSYNC1      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6124 E_SIO_OPEN_RILSYNC2      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6125 E_SIO_OPEN_RILSYNC3      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6126 E_SIO_OPEN_RILDEV        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6127 E_SIO_OPEN_RILDCTL       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6128 E_SIO_OPEN_RILSCTL       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6129 E_SIO_CLOSE_SETDTR       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x612A E_SIO_CLOSE_HANDLE       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x612B E_SIO_CLOSE_OBXREGWR     */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x612C E_SIO_CLOSE_OBXDCTL      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x612D E_SIO_CLOSE_OBXDEV       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x612E E_SIO_CLOSE_OBXREGCL     */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x612F E_SIO_CLOSE_RILDCTRL     */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6130 E_SIO_CLOSE_RILDEV       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6131 E_SIO_CLOSE_RILSYNC1     */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6132 E_SIO_CLOSE_RILSYNC2     */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6133 E_SIO_CLOSE_RILSYNC3     */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6134 E_SIO_CLOSE_RILEND       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6135 E_SIO_CLOSE_RILEVT       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6136 E_SIO_CLOSE_RILDLL       */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6137 E_SIO_RXCLR_PURGE        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6138 E_SIO_TXCLR_PURGE        */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x6139 E_SIO_PULSE_SETDTR1      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x613A E_SIO_PULSE_SETDTR2      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x613B E_SIO_STATE_GETSTATE     */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x613C E_SIO_STATE_BADFLAG      */
  SPIPC_DISCONNECT_LOC_SOFTWARE,     /* 0x613D E_SIO_LINE_GETLINE       */
  SPIPC_DISCONNECT_USR_HANGUP_LOC,   /* 0x613E E_SIO_LINE_SIGTERM       */
  SPIPC_DISCONNECT_LOC_MODEMTALK,    /* 0x613F E_SIO_LINE_NODSR         */
  SPIPC_DISCONNECT_USR_HANGUP_REM,   /* 0x6140 E_SIO_LINE_NODCD         */
  SPIPC_DISCONNECT_LOC_MODEMTALK     /* 0x6141 E_SIO_LINE_RINGING       */
};

/*============================================================================*/
/*                 C  P  H  O  N  E   -   C  O  M  M  A  N  D                 */
/*============================================================================*/

/*------------------*/
/*  COMMAND-THREAD  */
/*------------------*/

DWORD WINAPI cmd_thread (LPVOID ptr)                        /* Command Thread */
{
  HANDLE heap,thnd,eventlist[2];
  SPIPC_VERSIONINFO ipcver;
  SPIPC_QUEUEINFO ipcqueue;
  struct phone_link link;
  unsigned short x;
  signed short n,m;
  unsigned char c;
  SPIPC_HEADER *h;
  DWORD d,e;
  BOOL b;
  int i;

  /* Init ipc */
  if (ptr == NULL)
    return E_CMD_NULLPTR;
  eventlist[0] = *((HANDLE *)ptr);
  i = SPIPC_getVersionInfo (&ipcver);
  if (i < 0)
    return i;
  if (ipcver.magic != K_SPIPC_MAGIC)
    return E_CMD_IPCDLL;
  i = SPIPC_getQueueInfo (K_SPIPC_QUEUE_COMMAND, &ipcqueue);
  if (i < 0)
    return i;
  eventlist[1] = ipcqueue.evt_rxrdy;
  if (ipcqueue.bytes_total > 0xFFFFL)
    x = 0xFFFF;
  else
  {
    x = (unsigned short)(ipcqueue.bytes_total);
    if (x < K_CMD_MINQUEUELEN)
      x = K_CMD_MINQUEUELEN;
  }
  heap = GetProcessHeap ();
  d = K_CMD_EVTQUEUELEN;
  d += x;
  cmd_evtbuf = HeapAlloc (heap, 0L, d);
  if (cmd_evtbuf == NULL)
    return E_CMD_NOMEM;
  e = HeapSize (heap, 0L, cmd_evtbuf);
  if ((e < d) || (e == 0xFFFFFFFFL))
  {
    HeapFree (heap, 0L, cmd_evtbuf);
    return E_CMD_NOMEM;
  }
  d = e;
  cmd_msgbuf = (unsigned char *)cmd_evtbuf + K_CMD_EVTQUEUELEN;
  d -= K_CMD_EVTQUEUELEN;
  if (d > 0xFFFFL)
    cmd_buflen = 0xFFFF;
  else
    cmd_buflen = (unsigned short)d;
  InitializeCriticalSection (&cmd_evtlck);
  thnd = GetCurrentThread ();

  /* Command loop */
  h = cmd_msgbuf;
  while (42)
  {
    d = WaitForMultipleObjects (2L, eventlist, FALSE, INFINITE);
    if (d == WAIT_FAILED)
    {
      n = E_CMD_WAITEVT;
      break;
    }
    if (d == WAIT_OBJECT_0 + 0)  /* Term-Event */
    {
      n = 0;
      break;
    }
    if (d == WAIT_OBJECT_0 + 1)  /* Command-Rx */
    {
      /* Read command */
      x = cmd_buflen;
      i = SPIPC_getMessage (K_SPIPC_QUEUE_COMMAND, cmd_msgbuf, &x, \
                            SPIPC_TIME_NOWAIT);
      if (i == E_SPIPC_EMPTY)
        continue;
      if (i < 0)
        goto err_msgio;
      if ((x != h->len) || (x < K_CMD_MSGHDRLEN) || (x > cmd_buflen))
      {
        n = E_CMD_MSGQUEUE;
        break;
      }
      if (h->msg & 0x8000)
        continue;
      switch (h->msg)
      {
        /* Handle commands */
        case SPIPC_CMD_VERSION:    /* 0x0000 */
          {
            SPIPC_MSG_RES_VERSION *p;
            p = cmd_msgbuf;
            p->hdr.len  = K_CMD_MSGHDRLEN + 3;
            p->hdr.msg  = SPIPC_RES_VERSION;
            p->major    = K_CMD_VERMAJ;
            p->minor    = K_CMD_VERMIN;
            p->revision = K_CMD_VERREV;
          }
          break;
        case SPIPC_CMD_PING:       /* 0x0001 */
          h ->msg = SPIPC_RES_PONG;
          break;
        case SPIPC_CMD_EXIT:       /* 0x0002 */
          {
            SPIPC_MSG_RES_EXIT *p;
            if (x != K_CMD_MSGHDRLEN)
              goto send_err_length;
            b = PostMessage (wintop_wnd, WM_CLOSE, 0L, 0L);
            if (!b)
              goto send_err_unable;
            p = cmd_msgbuf;
            p->hdr.len = K_CMD_MSGHDRLEN + 1;
            p->hdr.msg = SPIPC_RES_EXIT;
            p->term    = 1;
          }
          break;
        case SPIPC_CMD_OFF:        /* 0x0003 */
          {
            SPIPC_MSG_CMD_OFF *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_off (p->phone, &m);
            if ((n == 1) && (m < 0))
              n = m;
          }
          goto send_reply;
        case SPIPC_CMD_ON:         /* 0x0004 */
          {
            SPIPC_MSG_CMD_ON *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_on (p->phone);
          }
          goto send_reply;
        case SPIPC_CMD_HWINFO:     /* 0x0005 */
          {
            struct phone_hwinfo *info;
            SPIPC_MSG_RES_HWINFO *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            info = HeapAlloc (heap, 0L, sizeof (struct phone_hwinfo));
            if (info == NULL)
              goto send_err_unable;
            phone_hwdetect_create (info);
            p = cmd_msgbuf;
            x = 0;
            /**/
            phone_hwdetect_destroy (info);
            b = HeapFree (heap, 0L, info);
            if (!b)
            {
              send_err_unable:
              n = E_SPIPC_CMD_FAILED;
              goto send_error;
            }
            p->hdr.len = K_CMD_MSGHDRLEN + 1 + x;
            p->hdr.msg = SPIPC_RES_HWINFO;
          }
          break;
        case SPIPC_CMD_AUTOCFG:    /* 0x0006 */
          {
            SPIPC_MSG_CMD_AUTOCFG *p;
            if (x != (K_CMD_MSGHDRLEN + 4))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_autoconfig(p->phone, p->cfgtype, p->mdmport, p->mdmtype);
          }
          goto send_reply;
        case SPIPC_CMD_SETCFG:     /* 0x0007 */
          {
            SPIPC_MSG_CMD_SETCFG *p;
            if (x != (K_CMD_MSGHDRLEN + 1 + sizeof (struct phone_config)))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_setconfig (p->phone, \
                                 (const struct phone_config *)(p->cfgdata));
          }
          goto send_reply;
        case SPIPC_CMD_GETCFG:     /* 0x0008 */
          {
            SPIPC_MSG_RES_GETCFG *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_getconfig (p->phone, (struct phone_config *)(p->cfgdata));
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 1 + sizeof (struct phone_config);
            p->hdr.msg = SPIPC_RES_GETCFG;
          }
          break;
        case SPIPC_CMD_SETOUTVOL:  /* 0x0010 */
          {
            SPIPC_MSG_CMD_SETOUTVOL *p;
            if (x != (K_CMD_MSGHDRLEN + 4))
              goto send_err_length;
            p = cmd_msgbuf;
            n = audio_setoutvol (&(phone_base[p->phone].dseg->adseg), p->chan, \
                                 p->volume);
          }
          goto send_reply;
        case SPIPC_CMD_GETOUTVOL:  /* 0x0011 */
          {
            SPIPC_MSG_RES_GETOUTVOL *p;
            if (x != (K_CMD_MSGHDRLEN + 2))
              goto send_err_length;
            p = cmd_msgbuf;
            n = audio_getoutvol (&(phone_base[p->phone].dseg->adseg), p->chan, \
                                 &(p->volume));
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 4;
            p->hdr.msg = SPIPC_RES_GETOUTVOL;
          }
          break;
        case SPIPC_CMD_SETDECSTATE:/* 0x0040 */
          {
            SPIPC_MSG_CMD_SETDECSTATE *p;
            if (x != (K_CMD_MSGHDRLEN + 49))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_setdecstate (p->phone, p->key, p->cnt);
          }
          goto send_reply;
        case SPIPC_CMD_GETDECSTATE:/* 0x0041 */
          {
            SPIPC_MSG_RES_GETDECSTATE *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_getdecstate (p->phone, p->key, p->cnt);
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 49;
            p->hdr.msg = SPIPC_RES_GETDECSTATE;
          }
          break;
        case SPIPC_CMD_SETDECMODE: /* 0x0042 */
          {
            SPIPC_MSG_CMD_SETDECMODE *p;
            if (x != (K_CMD_MSGHDRLEN + 2))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_setdecmode (p->phone, p->mode);
          }
          goto send_reply;
        case SPIPC_CMD_GETDECMODE: /* 0x0043 */
          {
            SPIPC_MSG_RES_GETDECMODE *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_getdecmode (p->phone);
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 2;
            p->hdr.msg = SPIPC_RES_GETDECMODE;
            p->mode    = (unsigned char)n;
          }
          break;                   /* 0x0044 */
        case SPIPC_CMD_SETDECCODECTBL:
          {
            SPIPC_MSG_CMD_SETDECCODECTBL *p;
            if (x != (K_CMD_MSGHDRLEN + 3))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_setdeccodectbl (p->phone, p->index, p->codec);
          }
          goto send_reply;         /* 0x0045 */
        case SPIPC_CMD_GETDECCODECTBL:
          {
            SPIPC_MSG_RES_GETDECCODECTBL *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_getdeccodectbl (p->phone, p->codec);
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 3;
            p->hdr.msg = SPIPC_RES_GETDECCODECTBL;
          }
          break;
        case SPIPC_CMD_GETDECCODEC:/* 0x0046 */
          {
            SPIPC_MSG_RES_GETDECCODEC *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_getdeccodec (p->phone);
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 2;
            p->hdr.msg = SPIPC_RES_GETDECCODEC;
            p->index   = (unsigned char)n;
          }
          break;
        case SPIPC_CMD_GETDECSYNC: /* 0x0047 */
          {
            SPIPC_MSG_RES_GETDECSYNC *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_getdecsync (p->phone);
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 3;
            p->hdr.msg = SPIPC_RES_GETDECSYNC;
            p->sync    = (unsigned char)n;
          }
          break;
        case SPIPC_CMD_SETENCSTATE:/* 0x0060 */
          {
            SPIPC_MSG_CMD_SETENCSTATE *p;
            if (x != (K_CMD_MSGHDRLEN + 49))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_setencstate (p->phone, p->key, p->cnt);
          }
          goto send_reply;
        case SPIPC_CMD_GETENCSTATE:/* 0x0061 */
          {
            SPIPC_MSG_RES_GETENCSTATE *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_getencstate (p->phone, p->key, p->cnt);
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 49;
            p->hdr.msg = SPIPC_RES_GETENCSTATE;
          }
          break;
        case SPIPC_CMD_SETENCMODE: /* 0x0062 */
          {
            SPIPC_MSG_CMD_SETENCMODE *p;
            if (x != (K_CMD_MSGHDRLEN + 2))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_setencmode (p->phone, p->mode);
          }
          goto send_reply;
        case SPIPC_CMD_GETENCMODE: /* 0x0063 */
          {
            SPIPC_MSG_RES_GETENCMODE *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_getencmode (p->phone);
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 2;
            p->hdr.msg = SPIPC_RES_GETENCMODE;
            p->mode    = (unsigned char)n;
          }
          break;                   /* 0x0064 */
        case SPIPC_CMD_SETENCCODECTBL:
          {
            SPIPC_MSG_CMD_SETENCCODECTBL *p;
            if (x != (K_CMD_MSGHDRLEN + 3))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_setenccodectbl (p->phone, p->index, p->codec);
          }
          goto send_reply;         /* 0x0065 */
        case SPIPC_CMD_GETENCCODECTBL:
          {
            SPIPC_MSG_RES_GETENCCODECTBL *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_getenccodectbl (p->phone, p->codec);
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 3;
            p->hdr.msg = SPIPC_RES_GETENCCODECTBL;
          }
          break;
        case SPIPC_CMD_SETENCCODEC:/* 0x0066 */
          {
            SPIPC_MSG_CMD_SETENCCODEC *p;
            if (x != (K_CMD_MSGHDRLEN + 2))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_setenccodec (p->phone, p->index);
          }
          goto send_reply;
        case SPIPC_CMD_GETENCCODEC:/* 0x0067 */
          {
            SPIPC_MSG_RES_GETENCCODEC *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_getenccodec (p->phone);
            if (n < 0)
              goto send_error;
            p->hdr.len = K_CMD_MSGHDRLEN + 2;
            p->hdr.msg = SPIPC_RES_GETENCCODEC;
            p->index   = (unsigned char)n;
          }
          break;
        case SPIPC_CMD_TXUSERDATA: /* 0x0080 */
          {
            SPIPC_MSG_CMD_TXUSERDATA *p;
            SPIPC_MSG_MUX_TXUSERDATA *q;
            if (x < (K_CMD_MSGHDRLEN + 2))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_userdata (p->phone, p->hdr.id, p->userdata, \
                                (unsigned short)(x - K_CMD_MSGHDRLEN - 1));
            if (n < 0)
              goto send_error;
            q = cmd_msgbuf;
            q->hdr.len = K_CMD_MSGHDRLEN + 2;
            q->hdr.msg = SPIPC_MUX_TXUSERDATA;
            q->state = 0;
          }
          break;
        case SPIPC_CMD_HANGUP:     /* 0x0100 */
          {
            SPIPC_MSG_RES_DISCONNECT *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            n = phone_hangup (p->phone);
            p->hdr.len = K_CMD_MSGHDRLEN + 4;
            p->hdr.msg = SPIPC_RES_DISCONNECT;
            p->reason  = cmd__errorconv_disc (n);
            p->result  = n;
          }
          break;
        case SPIPC_CMD_ANSWER:     /* 0x0101 */
          {
            SPIPC_MSG_CMD_ANSWER *p;
            if (x != (K_CMD_MSGHDRLEN + 1))
              goto send_err_length;
            p = cmd_msgbuf;
            link.jobid         = p->hdr.id;
            link.dialout       = 0;
            link.service       = 0;
            link.carrier       = 0;
            link.protocol      = 0;
            link.baudrate      = 0L;
            link.diallength    = 0;
            link.dialstring[0] = 0;
            c = p->phone;
          }
          goto do_connect;
        case SPIPC_CMD_DIAL:       /* 0x0102 */
          {
            SPIPC_MSG_CMD_DIAL *p;
            if (x < (K_CMD_MSGHDRLEN + 6))
              goto send_err_length;
            p = cmd_msgbuf;
            if (x < (K_CMD_MSGHDRLEN + 6 + p->diallength))
            {
              send_err_length:
              n = E_SPIPC_CMD_BADLENGTH;
              goto send_error;
            }
            link.jobid    = p->hdr.id;
            link.dialout  = 1;
            link.service  = p->service;
            link.carrier  = p->carrier;
            link.protocol = p->protocol;
            link.baudrate = 0L;
            c = p->diallength;
            if (c >= K_PHONE_DIALNUMBUFLEN)
              c = K_PHONE_DIALNUMBUFLEN - 1;
            link.diallength = c;
            if (c)
              memcpy (link.dialstring, p->dialstring, c);
            link.dialstring[c] = 0;
            c = p->phone;
          }
          do_connect:
          n = phone_connect (c, &link);
          if (n < 0)
            goto send_error;
          h->len = 0;
          break;
        default:                   /* 0xNNNN */
          n = E_SPIPC_CMD_BADOPCODE;
          send_reply:
          if (n >= 0)
          {
            SPIPC_MSG_RES_OK *p;
            p = cmd_msgbuf;
            p->hdr.len = K_CMD_MSGHDRLEN + 2;
            p->hdr.msg = SPIPC_RES_OK;
            p->result  = n;
          }
          else
          {
            SPIPC_MSG_RES_ERROR *p;
            send_error:
            p = cmd_msgbuf;
            p->hdr.len = K_CMD_MSGHDRLEN + 2;
            p->hdr.msg = SPIPC_RES_ERROR;
            p->result  = n;
          }
      }
      /* Send result */
      if ((h->len >= K_CMD_MSGHDRLEN) && (h->len <= cmd_buflen))
      {
#ifndef _WIN32_WCE
        SetThreadPriority (thnd, K_AUDIO_INTPRIO);
#else
        CeSetThreadPriority (thnd, K_AUDIO_INTPRIO);
#endif
        i = SPIPC_putMessage (K_SPIPC_QUEUE_RESULT, cmd_msgbuf, \
                              SPIPC_TIME_FOREVER);
        SetThreadPriority (thnd, K_WINTOP_CMDPRIO);
        if (i < 0)
        {
          err_msgio:
          n = (signed short)i;
          break;
        }
      }
    }
  }

  /* Exit ipc */
  for (c=0; c<K_PHONE_MAXPHONES; c++)
  {
    m = phone_off (c, NULL);
    if ((m < 0) && (n >= 0))
      n = m;
  }
  DeleteCriticalSection (&cmd_evtlck);
  memset (cmd_evtbuf, 0, e);
  b = HeapFree (heap, 0L, cmd_evtbuf);
  if ((!b) && (n >= 0))
    n = E_CMD_MEMFREE;
  wintop_exit ();
  return n;
}

/*-----------------*/
/*  NOTIFICATIONS  */
/*-----------------*/
                                                            /* Event Callback */
void cmd_notify (unsigned char phone, unsigned char event, const void *info, \
                 signed short result)
{
  const struct phone_link *link;
  SPIPC_HEADER *h;
  HANDLE thnd;
  int prio;

  /* Send event-msg */
  link = info;
  h = cmd_evtbuf;
  thnd = GetCurrentThread ();
#ifndef _WIN32_WCE
  prio = GetThreadPriority (thnd);
  if (prio < K_AUDIO_INTPRIO)
    SetThreadPriority (thnd, K_AUDIO_INTPRIO);
#else
  prio = CeGetThreadPriority (thnd);
  if (prio > K_AUDIO_INTPRIO)
    CeSetThreadPriority (thnd, K_AUDIO_INTPRIO);
#endif
  EnterCriticalSection (&cmd_evtlck);
  switch (event)
  {
    case K_CMD_NOTIFY_RINGOFF:    /* 0 */
      {
        SPIPC_MSG_EVT_RINGOFF *p;
        p = cmd_evtbuf;
        p->hdr.len = K_CMD_MSGHDRLEN + 1;
        p->hdr.msg = SPIPC_EVT_RINGOFF;
        p->hdr.id  = SPIPC_MSGID_EVENT;
        p->phone   = phone;
      }
      break;
    case K_CMD_NOTIFY_RINGON:     /* 1 */
      cmd_flgclip = 0;
      {
        SPIPC_MSG_EVT_RINGON *p;
        p = cmd_evtbuf;
        p->hdr.len = K_CMD_MSGHDRLEN + 1;
        p->hdr.msg = SPIPC_EVT_RINGON;
        p->hdr.id  = SPIPC_MSGID_EVENT;
        p->phone   = phone;
      }
      break;
    case K_CMD_NOTIFY_RING:       /* 2 */
      {
        SPIPC_MSG_EVT_RING *p;
        p = cmd_evtbuf;
        p->hdr.id  = SPIPC_MSGID_EVENT;
        p->phone   = phone;
        if (!cmd_flgclip  && link->diallength)
        {
          SPIPC_MSG_EVT_CALLERID *q;
          cmd_flgclip = 1;
          q = cmd_evtbuf;
          q->hdr.len   = K_CMD_MSGHDRLEN + 2 + link->diallength;
          q->hdr.msg   = SPIPC_EVT_CALLERID;
          q->remnumlen = link->diallength;
          memcpy (q->remnumdata, link->dialstring, link->diallength);
          q->remnumdata[link->diallength] = 0;
          SPIPC_putMessage (K_SPIPC_QUEUE_RESULT, cmd_evtbuf, K_CMD_EVTWRTIME);
        }
        p->hdr.len = K_CMD_MSGHDRLEN + 1;
        p->hdr.msg = SPIPC_EVT_RING;
      }
      break;
    case K_CMD_NOTIFY_CONNECT_0:  /* 3 */
      cmd_flgdisc = 0;
      {
        if (!(link->dialout))
        {
          SPIPC_MSG_PRO_ANSWERSTART *p;
          p = cmd_evtbuf;
          p->hdr.len = K_CMD_MSGHDRLEN + 1;
          p->hdr.msg = SPIPC_PRO_ANSWERSTART;
          p->hdr.id  = link->jobid;
          p->phone   = phone;
        }
        else
        {
          SPIPC_MSG_PRO_DIALSTART *p;
          p = cmd_evtbuf;
          p->hdr.len    = K_CMD_MSGHDRLEN + 6 + link->diallength;
          p->hdr.msg    = SPIPC_PRO_DIALSTART;
          p->hdr.id     = link->jobid;
          p->phone      = phone;
          p->media      = SPIPC_LINKMEDIA_TEL;
          p->service    = link->service;
          p->carrier    = link->carrier;
          p->protocol   = link->protocol;
          p->diallength = link->diallength;
          memcpy (p->dialstring, link->dialstring, link->diallength);
          p->dialstring[link->diallength] = 0;
        }
      }
      break;
    case K_CMD_NOTIFY_CONNECT_1:  /* 4 */
      cmd_flgdisc = 1;
      {
        SPIPC_MSG_RES_CONNECT *p;
        p = cmd_evtbuf;
        p->hdr.len    = K_CMD_MSGHDRLEN + 11 + link->diallength;
        p->hdr.msg    = SPIPC_RES_CONNECT;
        p->hdr.id     = link->jobid;
        p->phone      = phone;
        p->dialout    = link->dialout;
        p->media      = SPIPC_LINKMEDIA_TEL;
        p->service    = link->service;
        p->baudrate   = link->baudrate;
        p->carrier    = link->carrier;
        p->protocol   = link->protocol;
        p->remnumlen  = link->diallength;
        memcpy (p->remnumdata, link->dialstring, link->diallength);
        p->remnumdata[link->diallength] = 0;
      }
      break;
    case K_CMD_NOTIFY_HANGUP:     /* 5 */
      {
        SPIPC_MSG_EVT_HANGUP *p;
        p = cmd_evtbuf;
        p->hdr.len = K_CMD_MSGHDRLEN + 1;
        p->hdr.msg = SPIPC_EVT_HANGUP;
        p->hdr.id  = SPIPC_MSGID_EVENT;
        p->phone   = phone;
      }
      break;
    case K_CMD_NOTIFY_FINAL:      /* 6 */
      if (!cmd_flgdisc)
      {
        SPIPC_MSG_RES_DISCONNECT *p;
        p = cmd_evtbuf;
        p->hdr.len = K_CMD_MSGHDRLEN + 4;
        p->hdr.msg = SPIPC_RES_DISCONNECT;
        p->hdr.id  = link->jobid;
        p->phone   = phone;
        p->reason  = cmd__errorconv_disc (result);
        p->result  = result;
        break;
      }
      h->len = 0;
      break;
    case K_CMD_NOTIFY_RXUSERDATA: /* 7 */
      {
        SPIPC_MSG_MUX_RXUSERDATA *p;
        p = cmd_evtbuf;
        p->hdr.len = K_CMD_MSGHDRLEN + 1 + (unsigned short)result;
        p->hdr.msg = SPIPC_MUX_RXUSERDATA;
        p->hdr.id  = SPIPC_MSGID_EVENT;
        p->phone   = phone;
        memcpy (p->userdata, info, (unsigned short)result);
      }
      break;
    case K_CMD_NOTIFY_TXUSERDATA: /* 8 */
      {
        const unsigned long *q;
        SPIPC_MSG_RES_OK *p;
        p = cmd_evtbuf;
        q = info;
        p->hdr.len = K_CMD_MSGHDRLEN + 2;
        p->hdr.msg = SPIPC_RES_OK;
        p->hdr.id  = *q;
        p->result  = 0;
      }
      break;
    case K_CMD_NOTIFY_RXSYNC:     /* 9 */
      {
        SPIPC_MSG_PRT_RXSYNC *p;
        const unsigned char *q;
        p = cmd_evtbuf;
        q = info;
        p->hdr.len = K_CMD_MSGHDRLEN + 2;
        p->hdr.msg = SPIPC_PRT_RXSYNC;
        p->hdr.id  = SPIPC_MSGID_EVENT;
        p->phone   = phone;
        p->sync    = *q;
      }
      break;
    case K_CMD_NOTIFY_RXCODEC:   /* 10 */
      {
        SPIPC_MSG_PRT_RXCODEC *p;
        const unsigned char *q;
        p = cmd_evtbuf;
        q = info;
        p->hdr.len = K_CMD_MSGHDRLEN + 2;
        p->hdr.msg = SPIPC_PRT_RXCODEC;
        p->hdr.id  = SPIPC_MSGID_EVENT;
        p->phone   = phone;
        p->index   = *q;
      }
      break;
    default:                      /* N */
      h->len = 0;
  }
  if (h->len)
    SPIPC_putMessage (K_SPIPC_QUEUE_RESULT, cmd_evtbuf, K_CMD_EVTWRTIME);
  LeaveCriticalSection (&cmd_evtlck);
#ifndef _WIN32_WCE
  SetThreadPriority (thnd, prio);
#else
  CeSetThreadPriority (thnd, prio);
#endif
}

/*====*/
                                                 /* Convert disconnect-reason */
static unsigned char cmd__errorconv_disc (signed short err)
{
  unsigned char n,x,y;

  err = ~err;
  x = (unsigned char)(err >> 8);
  y = (unsigned char)(err & 0xFF);
  if ((x == 0x11) && (y < K_CMD_ERRMAP11LEN))
    n = cmd__errormap11disc[y];
  else if ((x == 0x51) && (y < K_CMD_ERRMAP51LEN))
    n = cmd__errormap51disc[y];
  else if ((x == 0x52) && (y < K_CMD_ERRMAP52LEN))
    n = cmd__errormap52disc[y];
  else if ((x == 0x61) && (y < K_CMD_ERRMAP61LEN))
    n = cmd__errormap61disc[y];
  else
    n = SPIPC_DISCONNECT_UNSPECIFIED;
  return n;
}


/*** EOF ***/
